From 778aa7ade0107fa645ab1427132551d138c7334a Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Mon, 10 Sep 2012 14:36:23 -0400 Subject: [PATCH] GtkAccelLabel: add manual accel API Add an API to GtkAccelLabel for hardcoding the accel key to be displayed (ie: allowing us to bypass the GtkAccelGroup lookup). Use that from the GMenuModel-based GtkMenu construction code instead of passing around the accel group. This makes accel labels work in bloatpad again. This patch effectively removes any hope of automatic runtime accel changes in GMenuModel-based menus without additional application support but it leaves the door open for this to be supported again in the future (if we decide that it's important). https://bugzilla.gnome.org/show_bug.cgi?id=683738 --- gtk/gtk.symbols | 1 + gtk/gtkaccellabel.c | 54 +++++++++++++++++++++++++++++++++----- gtk/gtkaccellabel.h | 4 +++ gtk/gtkapplicationwindow.c | 2 +- gtk/gtkmodelmenu.c | 24 ++++++----------- gtk/gtkmodelmenu.h | 6 ++--- gtk/gtkmodelmenuitem.c | 33 ++++++++++++++++++----- gtk/gtkmodelmenuitem.h | 3 +-- 8 files changed, 91 insertions(+), 36 deletions(-) diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols index 614f528915..40d3a31b5c 100644 --- a/gtk/gtk.symbols +++ b/gtk/gtk.symbols @@ -65,6 +65,7 @@ gtk_accel_label_get_accel_width gtk_accel_label_get_type gtk_accel_label_new gtk_accel_label_refetch +gtk_accel_label_set_accel gtk_accel_label_set_accel_closure gtk_accel_label_set_accel_widget gtk_accel_map_add_entry diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c index 452f43cd32..d374faa871 100644 --- a/gtk/gtkaccellabel.c +++ b/gtk/gtkaccellabel.c @@ -104,6 +104,9 @@ struct _GtkAccelLabelPrivate gchar *accel_string; /* has set function */ guint accel_padding; /* should be style property? */ guint16 accel_string_width; /* seems to be private */ + + guint accel_key; /* manual accel key specification if != 0 */ + GdkModifierType accel_mods; }; static void gtk_accel_label_set_property (GObject *object, @@ -903,19 +906,31 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) "gtk-enable-accels", &enable_accels, NULL); - if (enable_accels && accel_label->priv->accel_closure) + if (enable_accels && (accel_label->priv->accel_closure || accel_label->priv->accel_key)) { - GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure); + guint accel_key = accel_label->priv->accel_key; + GdkModifierType accel_mods = accel_label->priv->accel_mods; + + /* If we don't have a hardcoded value, check the accel group */ + if (!accel_key) + { + GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure); + + if (key && key->accel_flags & GTK_ACCEL_VISIBLE) + { + accel_key = key->accel_key; + accel_mods = key->accel_mods; + } + } - if (key && key->accel_flags & GTK_ACCEL_VISIBLE) + /* If we found a key using either method, set it */ + if (accel_key) { GtkAccelLabelClass *klass; gchar *tmp; klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label); - tmp = _gtk_accel_label_class_get_accelerator_label (klass, - key->accel_key, - key->accel_mods); + tmp = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods); accel_label->priv->accel_string = g_strconcat (" ", tmp, NULL); g_free (tmp); } @@ -930,3 +945,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label) return FALSE; } + +/** + * gtk_accel_label_set_accel: + * @accel_label: a #GtkAccelLabel + * @accelerator_key: a keyval, or 0 + * @accelerator_mods: the modifier mask for the accel + * + * Manually sets a keyval and modifier mask as the accelerator rendered + * by @accel_label. + * + * If a keyval and modifier are explicitly set then these values are + * used regardless of any associated accel closure or widget. + * + * Providing an @accelerator_key of 0 removes the manual setting. + * + * Since: 3.6 + */ +void +gtk_accel_label_set_accel (GtkAccelLabel *accel_label, + guint accelerator_key, + GdkModifierType accelerator_mods) +{ + accel_label->priv->accel_key = accelerator_key; + accel_label->priv->accel_mods = accelerator_mods; + + gtk_accel_label_reset (accel_label); +} diff --git a/gtk/gtkaccellabel.h b/gtk/gtkaccellabel.h index a1a9e02b95..bf247f11ce 100644 --- a/gtk/gtkaccellabel.h +++ b/gtk/gtkaccellabel.h @@ -90,6 +90,10 @@ void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label, void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label, GClosure *accel_closure); gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label); +GDK_AVAILABLE_IN_3_6 +void gtk_accel_label_set_accel (GtkAccelLabel *accel_label, + guint accelerator_key, + GdkModifierType accelerator_mods); /* private */ gchar * _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, diff --git a/gtk/gtkapplicationwindow.c b/gtk/gtkapplicationwindow.c index 4c4eadcfdf..0632bed5e4 100644 --- a/gtk/gtkapplicationwindow.c +++ b/gtk/gtkapplicationwindow.c @@ -256,7 +256,7 @@ gtk_application_window_update_menubar (GtkApplicationWindow *window) g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section)); g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section)); - window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), window->priv->accels); + window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined)); gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window)); gtk_widget_show_all (window->priv->menubar); g_object_unref (combined); diff --git a/gtk/gtkmodelmenu.c b/gtk/gtkmodelmenu.c index bb6a711026..f2174dd89d 100644 --- a/gtk/gtkmodelmenu.c +++ b/gtk/gtkmodelmenu.c @@ -33,7 +33,6 @@ typedef struct { GMenuModel *model; - GtkAccelGroup *accels; GtkMenuShell *shell; guint update_idle; GSList *connected; @@ -107,7 +106,7 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding, { GtkMenuItem *item; - item = gtk_model_menu_item_new (model, item_index, action_namespace, binding->accels); + item = gtk_model_menu_item_new (model, item_index, action_namespace); gtk_menu_shell_append (binding->shell, GTK_WIDGET (item)); gtk_widget_show (GTK_WIDGET (item)); binding->n_items++; @@ -254,7 +253,6 @@ gtk_model_menu_bind (GtkMenuShell *shell, binding = g_slice_new (GtkModelMenuBinding); binding->model = g_object_ref (model); - binding->accels = NULL; binding->shell = shell; binding->update_idle = 0; binding->connected = NULL; @@ -266,30 +264,25 @@ gtk_model_menu_bind (GtkMenuShell *shell, static void -gtk_model_menu_populate (GtkMenuShell *shell, - GtkAccelGroup *accels) +gtk_model_menu_populate (GtkMenuShell *shell) { GtkModelMenuBinding *binding; binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding"); - binding->accels = accels; - gtk_model_menu_binding_populate (binding); } GtkWidget * gtk_model_menu_create_menu (GMenuModel *model, - const gchar *action_namespace, - GtkAccelGroup *accels) + const gchar *action_namespace) { GtkWidget *menu; menu = gtk_menu_new (); - gtk_menu_set_accel_group (GTK_MENU (menu), accels); gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, action_namespace, TRUE); - gtk_model_menu_populate (GTK_MENU_SHELL (menu), accels); + gtk_model_menu_populate (GTK_MENU_SHELL (menu)); return menu; } @@ -317,21 +310,20 @@ gtk_menu_new_from_model (GMenuModel *model) menu = gtk_menu_new (); gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE); - gtk_model_menu_populate (GTK_MENU_SHELL (menu), NULL); + gtk_model_menu_populate (GTK_MENU_SHELL (menu)); return menu; } GtkWidget * -gtk_model_menu_create_menu_bar (GMenuModel *model, - GtkAccelGroup *accels) +gtk_model_menu_create_menu_bar (GMenuModel *model) { GtkWidget *menubar; menubar = gtk_menu_bar_new (); gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); - gtk_model_menu_populate (GTK_MENU_SHELL (menubar), accels); + gtk_model_menu_populate (GTK_MENU_SHELL (menubar)); return menubar; } @@ -360,7 +352,7 @@ gtk_menu_bar_new_from_model (GMenuModel *model) menubar = gtk_menu_bar_new (); gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); - gtk_model_menu_populate (GTK_MENU_SHELL (menubar), NULL); + gtk_model_menu_populate (GTK_MENU_SHELL (menubar)); return menubar; } diff --git a/gtk/gtkmodelmenu.h b/gtk/gtkmodelmenu.h index 1bc27be3eb..a27c7bda4b 100644 --- a/gtk/gtkmodelmenu.h +++ b/gtk/gtkmodelmenu.h @@ -25,12 +25,10 @@ #include G_GNUC_INTERNAL -GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model, - GtkAccelGroup *accels); +GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model); G_GNUC_INTERNAL GtkWidget * gtk_model_menu_create_menu (GMenuModel *model, - const gchar *action_namespace, - GtkAccelGroup *accels); + const gchar *action_namespace); #endif /* __GTK_MODEL_MENU_H__ */ diff --git a/gtk/gtkmodelmenuitem.c b/gtk/gtkmodelmenuitem.c index 450cd9a4bf..61e10e5a3c 100644 --- a/gtk/gtkmodelmenuitem.c +++ b/gtk/gtkmodelmenuitem.c @@ -25,6 +25,7 @@ #include "gtkactionhelper.h" #include "gtkmodelmenu.h" #include "gtkwidgetprivate.h" +#include "gtkaccellabel.h" struct _GtkModelMenuItem { @@ -107,8 +108,7 @@ static void gtk_model_menu_item_setup (GtkModelMenuItem *item, GMenuModel *model, gint item_index, - const gchar *action_namespace, - GtkAccelGroup *accels) + const gchar *action_namespace) { GMenuAttributeIter *iter; GMenuModel *submenu; @@ -125,12 +125,12 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item, if (action_namespace) { gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL); - menu = gtk_model_menu_create_menu (submenu, namespace, accels); + menu = gtk_model_menu_create_menu (submenu, namespace); g_free (namespace); } else { - menu = gtk_model_menu_create_menu (submenu, section_namespace, accels); + menu = gtk_model_menu_create_menu (submenu, section_namespace); } gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); @@ -145,6 +145,26 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item, if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL)); + else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) + { + GdkModifierType modifiers; + guint key; + + gtk_accelerator_parse (g_variant_get_string (value, NULL), &key, &modifiers); + + if (key) + { + GtkAccelLabel *accel_label; + + /* Ensure that the GtkAccelLabel has been created... */ + (void) gtk_menu_item_get_label (GTK_MENU_ITEM (item)); + accel_label = GTK_ACCEL_LABEL (gtk_bin_get_child (GTK_BIN (item))); + g_assert (accel_label); + + gtk_accel_label_set_accel (accel_label, key, modifiers); + } + } + else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace, g_variant_get_string (value, NULL)); @@ -260,14 +280,13 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class) GtkMenuItem * gtk_model_menu_item_new (GMenuModel *model, gint item_index, - const gchar *action_namespace, - GtkAccelGroup *accels) + const gchar *action_namespace) { GtkModelMenuItem *item; item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL); - gtk_model_menu_item_setup (item, model, item_index, action_namespace, accels); + gtk_model_menu_item_setup (item, model, item_index, action_namespace); return GTK_MENU_ITEM (item); } diff --git a/gtk/gtkmodelmenuitem.h b/gtk/gtkmodelmenuitem.h index 9e35327f54..655f07341b 100644 --- a/gtk/gtkmodelmenuitem.h +++ b/gtk/gtkmodelmenuitem.h @@ -36,7 +36,6 @@ GType gtk_model_menu_item_get_type (void) G G_GNUC_INTERNAL GtkMenuItem * gtk_model_menu_item_new (GMenuModel *model, gint item_index, - const gchar *action_namespace, - GtkAccelGroup *accels); + const gchar *action_namespace); #endif /* __GTK_MODEL_MENU_ITEM_H__ */ -- 2.30.2